﻿using MainApp.Utils;
using MainApp.Utils.WindowsDesktops;
using NetOffice.OfficeApi.Tools;
using NetOffice.PowerPointApi;
using NetOffice.PowerPointApi.Enums;
using NetOffice.Tools;
using NetOffice.VBIDEApi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using PowerPointTools = NetOffice.PowerPointApi.Tools;

namespace AutoPntAddin
{
    [ComVisible(true)]
    [COMAddin("AutoPntAddin", "AutoPntAddin", LoadBehavior.LoadAtStartup)]
    [ProgId("AutoPntAddin.Connect"), Guid("0FE46D3E-BECD-4956-BBB9-D613FB80BC17"), Codebase, Timestamp]
    [RegistryLocation(RegistrySaveLocation.LocalMachine)]
    public partial class PntAddin : PowerPointTools.COMAddin
    {
        private Timer _timer;
        private bool _timerIsDoing = false;
        private VirtualDesktopManager _vdm = null;
        public PntAddin()
        {
            OnConnection += Addin_OnConnection;
            OnStartupComplete += Addin_OnStartupComplete;
            OnDisconnection += Addin_OnDisconnection;
        }

        private void Addin_OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
        {

        }

        private void Addin_OnDisconnection(ext_DisconnectMode removeMode, ref Array custom)
        {

        }

        private void Addin_OnStartupComplete(ref Array custom)
        {
            var application = Application;
            try
            {
                //application.PresentationOpenEvent += Application_PresentationOpenEvent;
                application.AfterPresentationOpenEvent += Application_AfterPresentationOpenEvent;
                application.ProtectedViewWindowOpenEvent += Application_ProtectedViewWindowOpenEvent;
                application.ProtectedViewWindowActivateEvent += Application_ProtectedViewWindowActivateEvent;
                application.PresentationCloseEvent += Application_PresentationCloseEvent;
                application.SlideShowEndEvent += Application_SlideShowEndEvent;
                application.SlideShowNextSlideEvent += Application_SlideShowNextSlideEvent;
                application.SlideShowNextClickEvent += Application_SlideShowNextClickEvent;
            }
            catch { }

            try { _vdm = new VirtualDesktopManager(); } catch { }
            _timer = new Timer(new TimerCallback(TimerCallback));
            _timer.Change(300, 1000);
        }

        private void Application_ProtectedViewWindowOpenEvent(ProtectedViewWindow protViewWindow)
        {
            try
            {
                protViewWindow.Edit();
            }
            catch { }
        }

        private void Application_ProtectedViewWindowActivateEvent(ProtectedViewWindow protViewWindow)
        {
            try
            {
                protViewWindow.Edit();
            }
            catch { }
        }

        private void TimerCallback(object state)
        {
            if (_timerIsDoing) return;
            try
            {
                _timerIsDoing = true;
                TryKeepDesktop();
            }
            catch { }
            finally
            {
                _timerIsDoing = false;
            }
        }

        /// <summary>
        /// 始终保持显示在当前的虚拟桌面中
        /// </summary>
        private void TryKeepDesktop()
        {
            var vdm = _vdm;
            if (vdm == null)
                return;
            try
            {
                var slideViewWindowHandles = GetSlideViewWindowHandles();
                var mappings = new List<HwndDesktopState>();
                if ((slideViewWindowHandles?.Length ?? 0) == 0) return;
                foreach (var handle in slideViewWindowHandles)
                {
                    bool indesktop = false;
                    try { indesktop = vdm.IsWindowOnCurrentVirtualDesktop(handle); }
                    catch { continue; }
                    var mapping = new HwndDesktopState
                    {
                        Handle = handle,
                        IsWindowOnCurrentVirtualDesktop = indesktop
                    };
                    mappings.Add(mapping);
                }
                //检查是否都处于当前桌面
                if (mappings.Count == 0 || mappings.All(p => p.IsWindowOnCurrentVirtualDesktop)) return;
                //将不在当前界面的窗口移入当前桌面
                using (var form = new System.Windows.Forms.Form()
                {
                    Width = 1,
                    Height = 1,
                    Left = -100,
                    Top = -100,
                    ShowInTaskbar = false,
                    FormBorderStyle = System.Windows.Forms.FormBorderStyle.None,
                })
                {
                    form.Show(null);
                    var desktopId = vdm.GetWindowDesktopId(form.Handle);
                    if (desktopId == Guid.Empty) return;
                    foreach (var mapping in mappings)
                    {
                        if (mapping.IsWindowOnCurrentVirtualDesktop) continue;
                        try { vdm.MoveWindowToDesktop(mapping.Handle, desktopId); } catch { }
                    }
                }
            }
            catch { }
        }

        /// <summary>
        /// 获取所有文档窗口句柄
        /// </summary>
        /// <returns></returns>
        private IntPtr[] GetDocumentWindowHandles()
        {
            var list = new List<IntPtr>();
            try
            {
                var windows = Application.Windows;
                if (windows.Count == 0) return list.ToArray();
                for (var index = windows.Count; index >= 1; index--)
                {
                    DocumentWindow window = null;
                    try { window = windows[index]; } catch { }
                    if (window == null)
                        continue;
                    var handle = PptWindowUtils.GetHwnd(window, out HwndSourceTypes _, ignoreCache: true);
                    if (handle > 0)
                    {
                        var hwnd = new IntPtr(handle);
                        list.Add(hwnd);
                    }
                }
            }
            catch { }
            return list.ToArray();
        }

        /// <summary>
        /// 获取所有的演示窗口句柄
        /// </summary>
        /// <returns></returns>
        private IntPtr[] GetSlideViewWindowHandles()
        {
            var list = new List<IntPtr>();
            try
            {
                var enumerator = new PptWindowUtils.WindowEnumerator(string.Empty, "screenClass");
                IntPtr[] handles = enumerator.EnumerateWindows(2000);
                if ((handles?.Length ?? 0) == 0) return list.ToArray();
                foreach (var handle in handles)
                {
                    if (handle == IntPtr.Zero) continue;
                    list.Add(handle);
                }
            }
            catch { }
            return list.ToArray();
        }

        private void Application_PresentationOpenEvent(Presentation pres)
        {
            try
            {
                SlideShowSettings settings = pres.SlideShowSettings;
                settings.RangeType = PpSlideShowRangeType.ppShowAll;
                settings.LoopUntilStopped = NetOffice.OfficeApi.Enums.MsoTriState.msoTrue;
                settings.Run();
            }
            catch { }
        }

        private void Application_AfterPresentationOpenEvent(Presentation pres)
        {
            Application_PresentationOpenEvent(pres);
        }

        private void Application_PresentationCloseEvent(Presentation pres)
        {
            try
            {
                //不保存文档修改(防止关闭时弹出保存对话框)
                if (pres.Saved == NetOffice.OfficeApi.Enums.MsoTriState.msoFalse)
                {
                    pres.Saved = NetOffice.OfficeApi.Enums.MsoTriState.msoTrue;
                }
            }
            catch { }
        }

        private void Application_SlideShowEndEvent(Presentation pres)
        {

        }

        private void Application_SlideShowNextSlideEvent(SlideShowWindow wn)
        {
            try
            {
                var pres = wn.Presentation;
                var slideCount = pres.Slides.Count;
                var slideShowWindow = pres.SlideShowWindow;
                if (slideShowWindow.View.Slide.SlideIndex == slideCount)
                {
                    //slideShowWindow.View.GotoSlide(1, NetOffice.OfficeApi.Enums.MsoTriState.msoTrue);
                }
            }
            catch { }
        }

        private void Application_SlideShowNextClickEvent(SlideShowWindow wn, Effect nEffect)
        {
            try
            {
                var pres = wn.Presentation;
                var slideCount = pres.Slides.Count;
                var slideShowWindow = wn;
                var clickCount = slideShowWindow.View.GetClickCount();
                var clickIndex = slideShowWindow.View.GetClickIndex();
            }
            catch { }
        }
    }

    class HwndDesktopState
    {
        public IntPtr Handle { get; set; }
        public bool IsWindowOnCurrentVirtualDesktop { get; set; }
    }
}
